// Copyright (c) 2023 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use ylong_xml::{
    Document, DocumentMethod, ElementMethod, Encoding, ParentNodeMethod, ValuedNodeMethod,
};

const XML_TEXT: &str = r#"
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<project name="project-name">
    <libraries>
        <library groupId="org.example" artifactId="&lt;name&gt;" version="0.1"/>
        <library groupId="com.example" artifactId="&quot;cool-lib&amp;" version="999"/>
    </libraries>
    <module name="module-1">
        <files>
            <file name="somefile.java" type="java">
                Some &lt;java&gt; class
            </file>
            <file name="another_file.java" type="java">
                Another &quot;java&quot; class
            </file>
            <file name="config.xml" type="xml">
                Weird &apos;XML&apos; config
            </file>
        </files>
        <libraries>
            <library groupId="junit" artifactId="junit" version="1.9.5"/>
        </libraries>
    </module>
    <module name="module-2">
        <files>
            <file name="program.js" type="javascript">
                JavaScript &amp; program
            </file>
            <file name="style.css" type="css">
                Cascading style sheet: &#xA9; - &#1161;
            </file>
        </files>
    </module>
</project>
"#;

#[test]
fn sdv_ylong_xml() {
    let document = Document::from_text(XML_TEXT).unwrap();
    assert_eq!(document.version(), "1.0");
    assert_eq!(document.xml_encoding(), Some(Encoding::Utf8));
    assert_eq!(document.standalone(), Some(true));

    let project = document.document_element().unwrap();
    let name = project.get_attribute("name").unwrap();
    assert_eq!(name.value(), "project-name");

    {
        let list = project.get_elements("libraries");
        assert_eq!(list.len(), 1);
        let libraries = list.item(0).unwrap();
        {
            let list = libraries.get_elements("library");
            assert_eq!(list.len(), 2);
            let library1 = list.item(0).unwrap();
            let group_id = library1.get_attribute("groupId").unwrap();
            let artifact_id = library1.get_attribute("artifactId").unwrap();
            let version = library1.get_attribute("version").unwrap();
            assert_eq!(group_id.value(), "org.example");
            assert_eq!(artifact_id.value(), "<name>");
            assert_eq!(version.value(), "0.1");

            let library2 = list.item(1).unwrap();
            let group_id = library2.get_attribute("groupId").unwrap();
            let artifact_id = library2.get_attribute("artifactId").unwrap();
            let version = library2.get_attribute("version").unwrap();
            assert_eq!(group_id.value(), "com.example");
            assert_eq!(artifact_id.value(), "\"cool-lib&");
            assert_eq!(version.value(), "999");
        }
    }

    {
        let list = project.get_elements("module");
        assert_eq!(list.len(), 2);
        let module1 = list.item(0).unwrap();
        let name = module1.get_attribute("name").unwrap();
        assert_eq!(name.value(), "module-1");
        {
            let list = module1.get_elements("files");
            assert_eq!(list.len(), 1);
            let files = list.item(0).unwrap();
            {
                let list = files.get_elements("file");
                assert_eq!(list.len(), 3);
                let file1 = list.item(0).unwrap();
                let name = file1.get_attribute("name").unwrap();
                let ty = file1.get_attribute("type").unwrap();
                assert_eq!(name.value(), "somefile.java");
                assert_eq!(ty.value(), "java");
                {
                    let children = file1.children();
                    assert_eq!(children.len(), 1);
                    let text = children.item(0).unwrap().into_text().unwrap();
                    assert_eq!(text.value(), "Some <java> class")
                }

                let file2 = list.item(1).unwrap();
                let name = file2.get_attribute("name").unwrap();
                let ty = file2.get_attribute("type").unwrap();
                assert_eq!(name.value(), "another_file.java");
                assert_eq!(ty.value(), "java");
                {
                    let children = file2.children();
                    assert_eq!(children.len(), 1);
                    let text = children.item(0).unwrap().into_text().unwrap();
                    assert_eq!(text.value(), "Another \"java\" class");
                }

                let file3 = list.item(2).unwrap();
                let name = file3.get_attribute("name").unwrap();
                let ty = file3.get_attribute("type").unwrap();
                assert_eq!(name.value(), "config.xml");
                assert_eq!(ty.value(), "xml");
                {
                    let children = file3.children();
                    assert_eq!(children.len(), 1);
                    let text = children.item(0).unwrap().into_text().unwrap();
                    assert_eq!(text.value(), "Weird 'XML' config");
                }
            }

            let list = module1.get_elements("libraries");
            assert_eq!(list.len(), 1);
            let libraries = list.item(0).unwrap();
            {
                let list = libraries.get_elements("library");
                let library = list.item(0).unwrap();
                let group_id = library.get_attribute("groupId").unwrap();
                let artifact_id = library.get_attribute("artifactId").unwrap();
                let version = library.get_attribute("version").unwrap();
                assert_eq!(group_id.value(), "junit");
                assert_eq!(artifact_id.value(), "junit");
                assert_eq!(version.value(), "1.9.5");
            }
        }

        let module2 = list.item(1).unwrap();
        let name = module2.get_attribute("name").unwrap();
        assert_eq!(name.value(), "module-2");
        {
            let list = module2.get_elements("files");
            assert_eq!(list.len(), 1);
            let files = list.item(0).unwrap();
            {
                let list = files.get_elements("file");
                assert_eq!(list.len(), 2);
                let file1 = list.item(0).unwrap();
                let name = file1.get_attribute("name").unwrap();
                let ty = file1.get_attribute("type").unwrap();
                assert_eq!(name.value(), "program.js");
                assert_eq!(ty.value(), "javascript");
                {
                    let children = file1.children();
                    assert_eq!(children.len(), 1);
                    let text = children.item(0).unwrap().into_text().unwrap();
                    assert_eq!(text.value(), "JavaScript & program")
                }

                let file2 = list.item(1).unwrap();
                let name = file2.get_attribute("name").unwrap();
                let ty = file2.get_attribute("type").unwrap();
                assert_eq!(name.value(), "style.css");
                assert_eq!(ty.value(), "css");
                {
                    let children = file2.children();
                    assert_eq!(children.len(), 1);
                    let text = children.item(0).unwrap().into_text().unwrap();
                    assert_eq!(text.value(), "Cascading style sheet: \u{a9} - \u{489}");
                }
            }
        }
    }
}
